// partially from ucc
#if !defined TOKEN && !defined KEY_A
#error "You must define TOKEN or KEY_A macro before include this file"
#endif

#ifndef TOKEN
#define TOKEN(...)
#endif

// all keys include c and p4
#ifndef KEY_A
#define KEY_A TOKEN
#endif

#ifdef INCLUDE_C_KEY_WORDS
#define TOK_C TOKEN
#ifndef KEY_C
#define KEY_C KEY_A
#endif
#else
#define TOK_C(...)
#define KEY_C(...)
#endif

#ifdef INCLUDE_P4_KEY_WORDS
#define TOK_4 TOKEN
#ifndef KEY_4
#define KEY_4 KEY_A
#endif
#else
#define TOK_4(...)
#define KEY_4(...)
#endif

#ifdef INCLUDE_PY_KEY_WORDS
#define TOK_P TOKEN
#ifndef KEY_P
#define KEY_P KEY_A
#endif
#else
#define TOK_P(...)
#define KEY_P(...)
#endif

/* keywords */
// C only
KEY_C(TK_AUTO,      "auto")
KEY_A(TK_EXTERN,    "extern")
KEY_C(TK_REGISTER,  "register")
KEY_C(TK_STATIC,    "static")
KEY_A(TK_TYPEDEF,   "typedef")
KEY_A(TK_CONST,     "const")
KEY_C(TK_VOLATILE,  "volatile")
KEY_C(TK_SIGNED,    "signed")
KEY_C(TK_UNSIGNED,  "unsigned")
KEY_C(TK_SHORT,     "short")
KEY_C(TK_LONG,      "long")
KEY_C(TK_CHAR,      "char")
KEY_A(TK_INT,       "int")
KEY_C(TK_INT64,     "__int64")
KEY_C(TK_FLOAT,     "float")
KEY_C(TK_DOUBLE,    "double")
KEY_A(TK_ENUM,      "enum")
KEY_A(TK_STRUCT,    "struct")
KEY_C(TK_UNION,     "union")
KEY_A(TK_VOID,      "void")
KEY_A(TK_BREAK,     "break")
KEY_C(TK_CASE,      "case")
KEY_C(TK_CONTINUE,  "continue")
KEY_A(TK_DEFAULT,   "default")
KEY_C(TK_DO,        "do")
KEY_A(TK_ELSE,      "else")
KEY_C(TK_FOR,       "for")
KEY_C(TK_GOTO,      "goto")
KEY_A(TK_IF,        "if")
KEY_A(TK_RETURN,    "return")
KEY_A(TK_SWITCH,    "switch")
KEY_C(TK_WHILE,     "while")
KEY_C(TK_SIZEOF,    "sizeof")

/* identifier */
TOKEN(TK_ID,        "ID")

/* constant */
KEY_A(TK_INTCONST,     "int")
TOK_C(TK_UINTCONST,    "unsigned int")
TOK_C(TK_LONGCONST,    "long")
TOK_C(TK_ULONGCONST,   "unsigned long")
TOK_C(TK_LLONGCONST,   "long long")
TOK_C(TK_ULLONGCONST,  "unsigned long long")
TOK_C(TK_FLOATCONST,   "float")
TOK_C(TK_DOUBLECONST,  "double")
TOK_C(TK_LDOUBLECONST, "long double")
TOKEN(TK_WIDESTRING,   "wstring")

/* operators */
TOKEN(TK_COMMA,         ",")
TOKEN(TK_QUESTION,      "?")
TOKEN(TK_COLON,         ":")
TOKEN(TK_ASSIGN,        "=")
TOK_C(TK_BITOR_ASSIGN,  "|=")
TOK_C(TK_BITXOR_ASSIGN, "^=")
TOK_C(TK_BITAND_ASSIGN, "&=")
TOK_C(TK_LSHIFT_ASSIGN, "<<=")
TOK_C(TK_RSHIFT_ASSIGN, ">>=")
TOK_C(TK_ADD_ASSIGN,    "+=")
TOK_C(TK_SUB_ASSIGN,    "-=")
TOK_C(TK_MUL_ASSIGN,    "*=")
TOK_C(TK_DIV_ASSIGN,    "/=")
TOK_C(TK_MOD_ASSIGN,    "%=")
TOKEN(TK_OR,            "||")
TOKEN(TK_AND,           "&&")
TOKEN(TK_BITOR,         "|")
TOKEN(TK_BITXOR,        "^")
TOKEN(TK_BITAND,        "&")
TOKEN(TK_EQUAL,         "==")
KEY_P(TK_IS,            "is")
TOKEN(TK_UNEQUAL,       "!=")
TOKEN(TK_GREAT,         ">")
TOKEN(TK_LESS,          "<")
TOKEN(TK_GREAT_EQ,      ">=")
TOKEN(TK_LESS_EQ,       "<=")
TOKEN(TK_LSHIFT,        "<<")
TOK_C(TK_RSHIFT,        ">>")
TOKEN(TK_ADD,           "+")
TOKEN(TK_SUB,           "-")
TOK_C(TK_MUL,           "*")
TOK_C(TK_DIV,           "/")
TOK_C(TK_MOD,           "%")
TOKEN(TK_INC,           "++")
TOK_C(TK_DEC,           "--")
TOKEN(TK_NOT,           "!")
TOKEN(TK_COMP,          "~")
TOKEN(TK_DOT,           ".")
TOK_C(TK_POINTER,       "->")
TOKEN(TK_LPAREN,        "(")
TOKEN(TK_RPAREN,        ")")
TOKEN(TK_LBRACKET,      "[")
TOKEN(TK_RBRACKET,      "]")

/* punctuators */
TOKEN(TK_LBRACE,        "{")
TOKEN(TK_RBRACE,        "}")
TOKEN(TK_SEMICOLON,     ";")
TOKEN(TK_ELLIPSIS,       "...")
TOKEN(TK_POUND,         "#")
TOKEN(TK_NEWLINE,       "\n")

KEY_4(TK_ABSTRACT,     "abstract")
KEY_4(TK_ACTION,       "action")
KEY_4(TK_ACTIONS,      "actions")
KEY_4(TK_APPLY,        "apply")
KEY_4(TK_BOOL,         "bool")
KEY_4(TK_BIT,          "bit")
KEY_4(TK_CONTROL,      "control")
KEY_4(TK_ENTRIES,      "entries")
KEY_4(TK_ERROR,        "error")
KEY_4(TK_EXIT,         "exit")
KEY_P(TK_FALSE,        "false")
KEY_4(TK_HEADER,       "header")
KEY_4(TK_HEADER_UNION, "header_union")
KEY_4(TK_IN,           "in")
KEY_4(TK_INOUT,        "inout")
KEY_4(TK_KEY,          "key")
KEY_4(TK_MATCH_KIND,   "match_kind")
KEY_4(TK_TYPE,         "type")
KEY_4(TK_PARSER,       "parser")
KEY_4(TK_PACKAGE,      "package")
KEY_4(TK_STATE,        "state")
TOKEN(TK_STRING,       "string")
KEY_4(TK_TABLE,        "table")
KEY_4(TK_THIS,         "this")
KEY_4(TK_TRANSATION,   "transition")
KEY_P(TK_TRUE,         "true")
KEY_4(TK_TUPLE,        "tuple")
KEY_4(TK_VARBIT,       "varbit")
KEY_4(TK_VALUE_SET,    "value_set")
KEY_4(TK_MASK,         "&&&")
KEY_4(TK_RANGE,        "..")

TOK_4(TK_WIDTH,       "width")
// KEY_P(TK_PRINT,       "print")
KEY_P(TK_IMPORT,      "import")
KEY_P(TK_DEF,         "def")
KEY_P(TK_CLASS,       "class")
KEY_P(TK_GLOBAL,      "global")
KEY_P(TK_NULL,        "none")

// KEY_4(TK_DONTCARE,       "_")

#ifdef TOKEN
#undef TOKEN
#endif

#ifdef TOK_C
#undef TOK_C
#endif

#ifdef TOK_4
#undef TOK_4
#endif

#ifdef KEY_A
#undef KEY_A
#endif

#ifdef KEY_C
#undef KEY_C
#endif

#ifdef KEY_4
#undef KEY_4
#endif